# 继承 (opens new window)(Inheritance)

# 定义

  • 子类对父类进行扩展,从一般到特殊的关系,父类放共性,子类放特性
  • 继承表达的是一种“是(is-a)”的关系

# 语法格式

在定义子类(sub class)的时候使用 extends 来表明自己继承于哪一个父类(super class)

class SubClass extends SuperClass {
    // 子类特有的字段和方法
}
1
2
3

# 作用

  • 描述一个体系
  • 其次解决代码重复

# 注意

  • 只允许单继承,不允许多继承,支持多重继承
  • java.lang.Object 类是 Java 语言的根类,任何类都是 Object 类的子类 / 间接子类

多继承会造成:

  1. 若子类继承的父类中拥有相同的成员变量,子类在引用该变量时将无法判别使用哪个父类的成员变量
  2. 若一个子类继承的多个父类拥有相同方法,同时子类并未覆盖该方法(若覆盖,则直接使用子类中该方法),那么调用该方法时将无法确定调用哪个父类的方法

# 子类可以访问的父类成员

  • 可访问
    • publicprotected 修饰的成员
    • 同包中缺省访问权限修饰符的成员
  • 不可以直接访问
    • 不同包中缺省访问权限修饰符的成员
    • private 修饰成员

# 子类初始化过程

  • 调用子类构造器之前一定会调用父类中可以被子类访问的构造器,完成父类字段初始化操作,隐式调用父类无参数构造器 super();(从该类所在继承树最顶层类的构造器开始执行)
  • 若父类没有可以被子类访问的无参数构造器,那么子类必须显式通过 super 语句调用父类带参数的构造器

# super 关键字

# 定义

  • 代表当前对象的父类对象

# 作用

  • 在子类的构造方法中调用父类的指定构造器 super(name, age);(必须作为构造方法中的第一条语句)
  • 在子类中访问父类的被隐藏的实例变量或调用父类的被覆盖的实例方法 super.name super.fly();

# 方法覆盖 Override

# 作用

  • 解决子类继承父类之后,可能父类的某一个方法不满足子类的具体特征,此时需要重新在子类中定义该方法,并重写方法体

# 原则(一同两小一大)

  • 一同:实例方法签名必须相同

  • 两小:

    1. 子类方法的返回值类型和父类方法的返回类型相同或者是其子类
    2. 子类方法声明抛出的异常类和父类方法声明抛出的异常类相同或者是其子类(运行时异常除外)
      • 子类方法中声明抛的异常小于或等于父类方法声明抛出异常类
      • 子类方法可以同时声明抛出多个属于父类方法声明抛出异常类的子类(子类也可以不声明抛出)
  • 一大:子类方法的访问权限比父类方法访问权限更大或相等(防止父类方法失传)

  • @Override 标签

# 注意

  • 书写方法覆盖直接拷贝父类的方法定义,修改方法体
  • 只有非 private、final 修饰的实例方法才有覆盖的概念
  • 隐藏父类方法父类字段(字段名相同,不管类型)、本类字段(局部变量)
class SuperClass {
    public String name = "superClass.name";

    public static void ooxx() {
    }
}

class SubClass extends SuperClass {
    public int name = 18; // 隐藏了父类的 name 字段

    public void doWork() {
        boolean name = false; //隐藏了本类中的 name 字段
        System.out.println(name); // false
        System.out.println(this.name); // 18
        System.out.println(super.name); //superClass.name
    }

    // 隐藏,不是方法覆盖
    public static void ooxx() {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class SubSubClass extends SubClass {
    protected int a = 30;

    public void accessData() {
        System.out.println(a); // 30
        System.out.println(super.a); // 20
        // System.out.println(super.super.a); // 编译报错
        System.out.println(((BaseClass) this).a); // 10
        System.out.println(((SubClass) this).a); // 20

        // 方法覆盖
        System.out.println(m()); // SubClass
        System.out.println(super.m()); // SubClass
        System.out.println(((BaseClass) this).m()); // SubClass
        System.out.println(((SubClass) this).m()); // SubClass
    }
}

class SubClass extends BaseClass {
    protected int a = 20;

    public String m() {
        return "SubClass";
    }
}

class BaseClass {
    protected int a = 10;

    public String m() {
        return "BaseClass";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 组合(Composite)

  • 旧类对象 作为 新类的成员变量 组合进来,用以实现新类的功能
  • 在 类 B 中创建一个 类 A 类型的对象,通过该对象调用类 A 的方法
  • 组合表达的是“有(has-a)”的关系
// private ArrayUtil util = new ArrayUtil();

public class OldClass {
    public void method() {
        System.out.println("旧类中的功能");
    }
}

public class NewClass {
    // 将旧类组合到新类,作为新类的一个组合成分
    private OldClass obj = new OldClass();
    // 重新定义自己的 method() 方法
    public void method() {
        // 直接复用 OldClass 提供的 method() 方法来实现自己的 method() 方法
        obj.method();
    }
}

public class CompositeDemo {
    public static void main(String[] args) {
        NewClass n = new NewClass();
        n.method();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Updated at: 2022-05-20 14:15:02